package dima.vigenere;

import org.apache.log4j.Logger;

/**
 * Created by IntelliJ IDEA.
 * User: dima
 * Date: 09.10.2010
 * Time: 1:36:15
 * класс реализующий алгоритм шифрования Виженера 
 */
public class Crypter {
    public static final String ALPHABET = " абвгдежзийклмнопрстуфхцчшщъыьэюя";
    public static final int ALPHABET_LEN = ALPHABET.length();
    public static final Logger log = Logger.getLogger(Crypter.class);

    /**
     * функция шифрования/расшифрования по алгоритму Виженера
     * @param text открытый текст
     * @param key ключ шифрования
     * @param mode true - шифрование; false - расшифровывание
     * @return зашифрованый/расшифрованый текст
     */
    public static String crypt(String text, String key, boolean mode) {
        String cipher = "";
//      выбор шифрование/расшифрование
        operator funct;
        if (mode){
             log.info("start encrypt");
             funct = new operator(){
                @Override
                int calc(int num1, int num2) {
                    return num1 + num2;
                }
            };
        }else {
            log.info("start decrypt");
            funct = new operator(){
                @Override
                int calc(int num1, int num2) {
                    return num1 - num2;
                }
            };
        }
        log.info("ALPHABET = \""+ALPHABET+"\";");
        log.info("ALPHABET_LEN = "+ALPHABET_LEN+";");
//        разбиваю ключ на символы
        char[] textChars = new char[key.length()];
        for (int i=0;i<key.length();i++){
            textChars[i] = key.charAt(i);
        }
//        for log   <
            String splittedKey = "";
            for (char textChar : textChars) {
                splittedKey += textChar;
            }
            log.debug("key="+splittedKey);
//        for log   >
        
        for (int i = 0; i < text.length(); i++) {
            log.debug("#"+i);
//            вычисляю текущий номер символа ключа
            int correspondingKeyCharCode = i % key.length();
//            вычисляю номер ключевого символа в алфавите
            int charNum = ALPHABET.indexOf(textChars[correspondingKeyCharCode]);
            log.debug("символ  ключа = "+textChars[correspondingKeyCharCode]+"; его номер в алфавите = "+charNum);
//            номер в алфавите текущего символа текста
            int charIndexInAlphabet = ALPHABET.indexOf(text.charAt(i));
            log.debug("символ текста = "+text.charAt(i)+"; его номер в алфавите = "+charIndexInAlphabet);
//            вычисляю новый символ
            char newChar = ALPHABET.charAt((funct.calc(charIndexInAlphabet, charNum)+ALPHABET.length()) % ALPHABET.length());
            cipher += newChar;
            log.debug("новый символ  = "+newChar+";"+" его номер в алфавите = "+ALPHABET.indexOf(newChar));
        }
        return cipher;
    }

    /**
     * класс для подстановки +/- (шифрование/расшифрование)
     */
    abstract static class operator{
        abstract int calc(int num1, int num2);
    }
}